package game.test.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;

public class Network {
	public static final String DATA_SEPARATOR = "|";

	// Client packets
	public static final String CLIENT_INFO = "CLIENT_INFO";
	public static final String CLIENT_DISCONNECT = "CLIENT_DISCONNECT";
	public static final String CLIENT_SETPOS = "CLIENT_SETPOS";

	// Server packets
	public static final String SERVER_STOP = "SERVER_STOP";
	public static final String SERVER_ACCEPT = "SERVER_ACCEPT";

	private boolean running = false;
	private Game game;
	private String ip = "localhost";
	private int port = 8755;
	private Socket server;
	private PrintWriter out;
	private BufferedReader in;
	private Thread listenThread;
	private int maxTimeout = 10000;
	public String reason = "";
	private ArrayList<Client> clients = new ArrayList<Client>();

	public Network(Game game) {
		this.game = game;
	}

	public boolean connect() {
		running = true;
		System.out.println("Connecting to the server...");
		try {
			server = new Socket();
			server.connect(new InetSocketAddress(ip, port), maxTimeout);
		} catch (Exception e) {
			System.out.println("Failed to connect to the server: "
					+ e.getMessage());
			reason = e.getMessage();
			return false;
		}

		try {
			server.setSoTimeout(maxTimeout);
		} catch (SocketException e) {
			System.out.println("Server timed out!");
			disconnect();
		}

		try {
			in = new BufferedReader(new InputStreamReader(
					server.getInputStream()));
			out = new PrintWriter(server.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		System.out.println("Connected!");
		return true;
	}

	private void process(String data) {
		String d[] = data.split(DATA_SEPARATOR);

		switch (d[0]) {
		case CLIENT_INFO:
			if (d.length == 2) {
				addClient(new Client(d[1]));
			} else {
				System.out.println("Invalid packet: " + data);
			}
			break;
		}
	}

	public void addClient(Client client) {
		clients.add(client);
	}
	
	public void removeClient(Client client) {
		clients.remove(client);
	}

	public void disconnect() {
		running = false;
		System.out.println("Disconnecting...");
		try {
			if (in != null) {
				in.close();
			}
			if (out != null) {
				out.close();
			}
			if (server != null) {
				server.close();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setServerProperties(String ip, int port) {
		if (ip != null) {
			this.ip = ip;
		}
		if (port != -1) {
			this.port = port;
		}
	}

	public void send(String data) {
		if (running) {
			out.println(data);
		}
	}

	public void startListening() {
		listenThread = new Thread(new Runnable() {
			public void run() {
				while (running) {
					try {
						if (in != null) {
							String data = in.readLine();
							if (data != null) {
								process(data);
							}
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		});
		listenThread.start();
	}
}
